#include "kernel/ilog.h"
#include "input/iinputsystem.h"
#include "input/ikeyboarddevice.h"
#include "inputsystemSDL.h"
#include "keyboarddeviceSDL.h"
#include "kernel/debug.h"
//#include "kernel/iengine.h"

namespace rengine3d {

	CKeyboardDeviceSDL::CKeyboardDeviceSDL(const string_t name, CInputSystemSDL* inputSys) {
		m_name			= name;
		m_inputSys		= inputSys;

		m_keys.resize(key_Count);
		m_keys.assign(m_keys.size(), false);

		memset(&m_keyBuffer, 0, 256 );
	}

	CKeyboardDeviceSDL::~CKeyboardDeviceSDL() {
		this->Shutdown();
	}

	void CKeyboardDeviceSDL::OnCharPress(int character, int action) {
	}

	void CKeyboardDeviceSDL::OnKeyPress(int key, int action) {
	}

	bool CKeyboardDeviceSDL::Init(void) {
		SDL_EnableUNICODE(1);
		SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

		return true;
	}

	void CKeyboardDeviceSDL::Shutdown(void) {
	}

	void CKeyboardDeviceSDL::Update(void) {

		m_keysPressed.clear();

		std::list<SDL_Event>::iterator it = m_inputSys->m_events.begin();
		for(; it != m_inputSys->m_events.end(); ++it) {
			SDL_Event *pEvent = &(*it);

			if(pEvent->type != SDL_KEYDOWN && pEvent->type != SDL_KEYUP) {
				continue;
			}

			keyboardKey_t key = SDLToKey(pEvent->key.keysym.sym);
			m_keys[key] = pEvent->type == SDL_KEYDOWN?true:false;

			if(pEvent->type == SDL_KEYDOWN)	{
				int sdl_mod = pEvent->key.keysym.mod;
				m_modifier = keyModifier_None;

				if(sdl_mod & KMOD_CTRL)		m_modifier |= keyModifier_Ctrl;
				if(sdl_mod & KMOD_SHIFT)	m_modifier |= keyModifier_Shift;
				if(sdl_mod & KMOD_ALT)		m_modifier |= keyModifier_Alt;

				m_keysPressed.push_back(keyPress_t(key, pEvent->key.keysym.unicode, m_modifier));
			}
		}
	}

	bool CKeyboardDeviceSDL::KeyIsDown(keyboardKey_t key) {
		return m_keys[key];
	}

	keyPress_t CKeyboardDeviceSDL::GetKey(void) {
		keyPress_t key = m_keysPressed.front();
		m_keysPressed.pop_front();
		return key;
	}

	bool CKeyboardDeviceSDL::KeyPressed() {
		return m_keysPressed.empty()==false;
	}

	keyboardKey_t CKeyboardDeviceSDL::SDLToKey(int key) {
		switch(key)
		{
		case	SDLK_BACKSPACE: return key_BACKSPACE;
		case	SDLK_TAB:return  key_TAB;
		case 	SDLK_CLEAR: return key_CLEAR;
		case 	SDLK_RETURN: return key_RETURN;
		case 	SDLK_PAUSE: return key_PAUSE;
		case 	SDLK_ESCAPE: return key_ESCAPE;
		case 	SDLK_SPACE: return key_SPACE;
		case 	SDLK_EXCLAIM: return key_EXCLAIM;
		case 	SDLK_QUOTEDBL: return key_QUOTEDBL;
		case 	SDLK_HASH: return key_HASH;
		case 	SDLK_DOLLAR: return key_DOLLAR;
		case 	SDLK_AMPERSAND: return key_AMPERSAND;
		case 	SDLK_QUOTE: return key_QUOTE;
		case 	SDLK_LEFTPAREN: return key_LEFTPAREN;
		case 	SDLK_RIGHTPAREN: return key_RIGHTPAREN;
		case 	SDLK_ASTERISK: return key_ASTERISK;
		case 	SDLK_PLUS: return key_PLUS;
		case 	SDLK_COMMA: return key_COMMA;
		case 	SDLK_MINUS: return key_MINUS;
		case 	SDLK_PERIOD: return key_PERIOD;
		case 	SDLK_SLASH: return key_SLASH;
		case 	SDLK_0: return key_0;
		case 	SDLK_1: return key_1;
		case 	SDLK_2: return key_2;
		case 	SDLK_3: return key_3;
		case 	SDLK_4: return key_4;
		case 	SDLK_5: return key_5;
		case 	SDLK_6: return key_6;
		case 	SDLK_7: return key_7;
		case 	SDLK_8: return key_8;
		case 	SDLK_9: return key_9;
		case 	SDLK_COLON: return key_COLON;
		case 	SDLK_SEMICOLON: return key_SEMICOLON;
		case 	SDLK_LESS: return key_LESS;
		case 	SDLK_EQUALS: return key_EQUALS;
		case 	SDLK_GREATER: return key_GREATER;
		case 	SDLK_QUESTION: return key_QUESTION;
		case 	SDLK_AT: return key_AT;
		case 	SDLK_LEFTBRACKET: return key_LEFTBRACKET;
		case 	SDLK_BACKSLASH: return key_BACKSLASH;
		case 	SDLK_RIGHTBRACKET: return key_RIGHTBRACKET;
		case 	SDLK_CARET: return key_CARET;
		case 	SDLK_UNDERSCORE: return key_UNDERSCORE;
		case 	SDLK_BACKQUOTE: return key_BACKQUOTE;
		case 	SDLK_a: return key_a;
		case 	SDLK_b: return key_b;
		case 	SDLK_c: return key_c;
		case 	SDLK_d: return key_d;
		case 	SDLK_e: return key_e;
		case 	SDLK_f: return key_f;
		case 	SDLK_g: return key_g;
		case 	SDLK_h: return key_h;
		case 	SDLK_i: return key_i;
		case 	SDLK_j: return key_j;
		case 	SDLK_k: return key_k;
		case 	SDLK_l: return key_l;
		case 	SDLK_m: return key_m;
		case 	SDLK_n: return key_n;
		case 	SDLK_o: return key_o;
		case 	SDLK_p: return key_p;
		case 	SDLK_q: return key_q;
		case 	SDLK_r: return key_r;
		case 	SDLK_s: return key_s;
		case 	SDLK_t: return key_t;
		case 	SDLK_u: return key_u;
		case 	SDLK_v: return key_v;
		case 	SDLK_w: return key_w;
		case 	SDLK_x: return key_x;
		case 	SDLK_y: return key_y;
		case 	SDLK_z: return key_z;
		case 	SDLK_DELETE: return key_DELETE;
		case 	SDLK_KP0: return key_KP0;
		case 	SDLK_KP1: return key_KP1;
		case 	SDLK_KP2: return key_KP2;
		case 	SDLK_KP3: return key_KP3;
		case 	SDLK_KP4: return key_KP4;
		case 	SDLK_KP5: return key_KP5;
		case 	SDLK_KP6: return key_KP6;
		case 	SDLK_KP7: return key_KP7;
		case 	SDLK_KP8: return key_KP8;
		case 	SDLK_KP9: return key_KP9;
		case 	SDLK_KP_PERIOD: return key_KP_PERIOD;
		case 	SDLK_KP_DIVIDE: return key_KP_DIVIDE;
		case 	SDLK_KP_MULTIPLY: return key_KP_MULTIPLY;
		case 	SDLK_KP_MINUS: return key_KP_MINUS;
		case 	SDLK_KP_PLUS: return key_KP_PLUS;
		case 	SDLK_KP_ENTER: return key_KP_ENTER;
		case 	SDLK_KP_EQUALS: return key_KP_EQUALS;
		case 	SDLK_UP: return key_UP;
		case 	SDLK_DOWN: return key_DOWN;
		case 	SDLK_RIGHT: return key_RIGHT;
		case 	SDLK_LEFT: return key_LEFT;
		case 	SDLK_INSERT: return key_INSERT;
		case 	SDLK_HOME: return key_HOME;
		case 	SDLK_END: return key_END;
		case 	SDLK_PAGEUP: return key_PAGEUP;
		case 	SDLK_PAGEDOWN: return key_PAGEDOWN;
		case 	SDLK_F1: return key_F1;
		case 	SDLK_F2: return key_F2;
		case 	SDLK_F3: return key_F3;
		case 	SDLK_F4: return key_F4;
		case 	SDLK_F5: return key_F5;
		case 	SDLK_F6: return key_F6;
		case 	SDLK_F7: return key_F7;
		case 	SDLK_F8: return key_F8;
		case 	SDLK_F9: return key_F9;
		case 	SDLK_F10: return key_F10;
		case 	SDLK_F11: return key_F11;
		case 	SDLK_F12: return key_F12;
		case 	SDLK_F13: return key_F13;
		case 	SDLK_F14: return key_F14;
		case 	SDLK_F15: return key_F15;
		case 	SDLK_NUMLOCK: return key_NUMLOCK;
		case 	SDLK_CAPSLOCK: return key_CAPSLOCK;
		case 	SDLK_SCROLLOCK: return key_SCROLLOCK;
		case 	SDLK_RSHIFT: return key_RSHIFT;
		case 	SDLK_LSHIFT: return key_LSHIFT;
		case 	SDLK_RCTRL: return key_RCTRL;
		case 	SDLK_LCTRL: return key_LCTRL;
		case 	SDLK_RALT: return key_RALT;
		case 	SDLK_LALT: return key_LALT;
		case 	SDLK_RMETA: return key_RMETA;
		case 	SDLK_LMETA: return key_LMETA;
		case 	SDLK_MODE: return key_MODE;
		case 	SDLK_HELP: return key_HELP;
		case 	SDLK_PRINT: return key_PRINT;
		case 	SDLK_SYSREQ: return key_SYSREQ;
		case 	SDLK_BREAK: return key_BREAK;
		case 	SDLK_MENU: return key_MENU;
		case 	SDLK_POWER: return key_POWER;
		}

		return key_NONE;

	}

	string_t CKeyboardDeviceSDL::KeyToString(keyboardKey_t key) {

		switch(key)
		{
		case key_ESCAPE:	return "escape";
		case key_1:			return "1";
		case key_2:			return "2";
		case key_3:			return "3";
		case key_4:			return "4";
		case key_5:			return "5";
		case key_6:			return "6";
		case key_7:			return "7";
		case key_8:			return "8";
		case key_9:			return "9";
		case key_0:			return "0";

		case key_LEFT:		return "left";
		case key_RIGHT:		return "right";
		case key_UP:		return "up";
		case key_DOWN:		return "down";

		}

		return "None";
	}

	keyboardKey_t CKeyboardDeviceSDL::StringToKey(string_t str) {
		return key_NONE;
	}

	uint CKeyboardDeviceSDL::GetModifiers(void) {
		return m_modifier;
	}

}
